package com.xmcc.service.impl;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

import com.xmcc.dao.SysAclMapper;
import com.xmcc.dao.SysRoleAclMapper;
import com.xmcc.dao.SysRoleMapper;

import com.xmcc.dao.SysRoleUserMapper;
import com.xmcc.dto.SysAclModuleTreeDto;
import com.xmcc.dto.SysAclTreeDto;
import com.xmcc.pojo.*;
import com.xmcc.service.SysAclModuleService;
import com.xmcc.service.SysCoreService;


import com.xmcc.utill.JedisUtils;
import com.xmcc.utill.ThreadLocalCommon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysCoreServiceImpl implements SysCoreService {
    @Autowired
    private SysAclModuleService sysAclModuleService;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysAclMapper sysAclMapper;
    @Autowired
    private JedisUtils jedisUtils;

    @Override
    public List<SysAclModuleTreeDto> coreTree(Integer roleId) {
        //获得模块的tree
        List<SysAclModuleTreeDto> list = sysAclModuleService.sysAclModuleTree();
        //把权限点查询出来 
        //取出当前用户
        SysUser sysUser = ThreadLocalCommon.popSysUser();
        Preconditions.checkNotNull(sysUser,"请先登录");
        //查询到当前用户所拥有的所有角色: 4 5
        List<SysRole> roleList = queryRoleByUser(sysUser.getId());
        //根据角色查询到所有权限点: 7 8 9 10 7
        List<SysAcl> aclList = queryAclByRoleId(roleList);
        //取出当前用户拥有的所有不重复的acl_id(去重):
        Set<Integer> userAclId = getAclId(aclList); // userAclId = 7 8 9 10 7 ？不明白
        //取出当前角色所有的不重复的acl_id，后台点击传说过来的roleId，假如roleId=4;
        List<SysRole> sigleRoleList= new ArrayList<>(); // 首先创建list集合存放 每个SysRole对象：
        SysRole sysRole = new SysRole();    //然后再创建SysRole对象
        sysRole.setId(roleId); // 把传过来的 roleId设置role对象中
        sigleRoleList.add(sysRole); // 把role对象放入array集合中 假如：role id=4
        List<SysAcl> currentAclList = queryAclByRoleId(sigleRoleList); // 把集合中的SysRole对象传入进去：role id=4
        //获得当前要授权的角色所拥有的所有权限点的id集合  aclId = 7 8 9 10
        Set<Integer> roleAclId = getAclId(currentAclList); // roleAclId = 7 8 9 10
        getTree(list,userAclId,roleAclId); // userAclId=当前user的拥有多少个角色再拥有多少个权限点，去重后的权限点id
        return list;                       // roleAclId=后台点击角色模块传过来的roleId，拥有的多少个权限点id
    }                                      // list 就是 最大模块的树，


    private void getTree(List<SysAclModuleTreeDto> list, Set<Integer> userAclId, Set<Integer> roleAclId) {
        if(CollectionUtils.isEmpty(list)){
            return;
        }
       List<SysAcl> sysAclList;
        SysAclTreeDto sysAclTreeDto;
        List<SysAclTreeDto> sysAclTreeDtoList;
        for (SysAclModuleTreeDto sysAclModuleTreeDto : list) { // 每个0级的对象：
            //根据每个模块或者子模块的id查询出所拥有的权限点对象list： 查到两个对象是：aclId = 11 12
            sysAclList = sysAclMapper.queryAclByModuleId(sysAclModuleTreeDto.getId()); //传入每个0级对象的Id = 1 2 3 6 10
            sysAclTreeDtoList = Lists.newArrayList();
            for (SysAcl sysAcl : sysAclList) { //然后循环该list的两个权限点的acl对象：
                sysAclTreeDto = SysAclTreeDto.getSysAclTreeDto(sysAcl); // 把sysAcl对象的属性赋值到SysAclTreeDto对象中
                //如果用户拥有这个权限点 就设置true
                if(userAclId.contains(sysAcl.getId())){ //userAclId = 7 8 9 10 7   aclId = 11 12
                    sysAclTreeDto.setHasAcl(true);
                }
                //当前角色已经拥有这个权限点
                if(roleAclId.contains(sysAcl.getId())){ // roleAclId = 7 8 9 10  aclId = 11 12
                    sysAclTreeDto.setChecked(true);
                }
                sysAclTreeDtoList.add(sysAclTreeDto); // 把每个sysAclTreeDto对象放入list集合中：
            }
            sysAclModuleTreeDto.setAclList(sysAclTreeDtoList); //把list集合放入模块树中SysAclModuleTreeDto
            //递归 把整个模块以树 呈现再前端：
            getTree(sysAclModuleTreeDto.getList(),userAclId,roleAclId);
        }

    }


    //查询到当前用户所拥有的所有角色
    public List<SysRole> queryRoleByUser(Integer userId){
      return  sysRoleMapper.queryRoleByUser(userId);
    }

    //该方法查询出每个acl对象中的id放入到set集合中：
    public  Set<Integer> getAclId(List<SysAcl> aclList){
        Set<Integer> aclSet = aclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());
       /* for(SysAcl sysAcl : aclList){   7 8 9 10 7
            aclSet.add(sysAcl.getId());
        }*/
        return aclSet;
    }

    //根据角色role对象查询到该角色对象的所有权限点acl对象：
    public List<SysAcl> queryAclByRoleId(List<SysRole> roleList){
        if(CollectionUtils.isEmpty(roleList)){
            return Lists.newArrayList();
        }
        return  sysAclMapper.queryAclByRoleId(roleList);
    }

    //filter拦截的redis缓存设置：
    @Override
    public Set<Integer> getAclIdByUser(Integer userId) {
        //首先走缓存拿数据：
        Set<Integer> userAcl = jedisUtils.getUserAcl(userId);
        if(userAcl==null){//说明缓存中没有取到
            //查询当前用户所拥有的角色
            List<SysRole> sysRoles = queryRoleByUser(userId);
            //再根据角色查询权限
            List<SysAcl> sysAcls =queryAclByRoleId(sysRoles);
            //获得不重复的权限id
            userAcl = getAclId(sysAcls);
            //缓存没有取出来了 放入缓存
            jedisUtils.setUserAcl(userId,userAcl);
        }
        return userAcl;
    }

}
